<html>
<head><title>Edit test</title></head>
<style>
    h2 {
        margin-top: 20px;
    }
    div {
        border: 1px solid black;
        min-height: 10px;
    }
</style>
<body>
    <h2>Prevent Input event on TextInput when type to input element</h2>
    <pre>
        Chrome/Edge. Typing is prevented and Input event is not raised
        Firefox. Typing is not prevented. Input event is raised
    </pre>
    <input id="simpleInput" />
    <h2>Prevent Input event and typing on simple ContentEditable div</h2>
    <pre>
        Chrome/Edge. Typing is prevented. Input event is not raised
        Firefox. Typing is not prevented.
    </pre>
    <div contenteditable="true" id="simpleContentEditable"></div>
    <h2>Prevent Input event on TextInput event when type to element node</h2>
    <pre>
        Not for Firefox because Firefox does not support TextInput event
    </pre>
    <div contenteditable="true" id="contentEditableWithElementNode"><p><br/></p></div>
    <h2>Modify text node of ContentEditable div on TextInput event and prevent Input event</h2>
    <pre>
        Not for Firefox because Firefox does not support TextInput event
    </pre>
    <div contenteditable="true" id="contentEditableWithModify"><p>A</p></div>
    <h2>Type to ContentEditable div when selected node was replaced on TextInput event</h2>
    <pre>
        Not for Firefox because Firefox does not support TextInput event
    </pre>
    <div contenteditable="true" id="contentEditableWithReplace"><p>B</p></div>
</body>
<script type="text/javascript">
    const contentEditableWithModifyEl  = document.getElementById('contentEditableWithModify');
    const contentEditableWithReplaceEl = document.getElementById('contentEditableWithReplace');

    function onTextInput (event) {
        let needPreventDefault = true;

        if (isTargetElement(event.target, contentEditableWithModifyEl))
            changeNodeValueOnTextInput(event);

        if (isTargetElement(event.target, contentEditableWithReplaceEl)) {
            replaceEditableElementOnTextInput(event);

            needPreventDefault = false;
        }

        if(needPreventDefault)
            event.preventDefault();
    }

    function changeNodeValueOnTextInput(event) {
        contentEditableWithModifyEl.childNodes[0].childNodes[0].nodeValue += event.data;
    }

    function replaceEditableElementOnTextInput (event) {
        if (window.preventNextElementReplacement)
            return;

        window.preventNextElementReplacement = true;

        const paragraph    = contentEditableWithReplaceEl.childNodes[0];
        const newParagraph = document.createElement("P");

        newParagraph.innerHTML = 'X';

        contentEditableWithReplaceEl.removeChild(paragraph);
        contentEditableWithReplaceEl.appendChild(newParagraph);
        newParagraph.focus();
    }

    function onInput (event) {
        if (!isTargetElement(event.target, contentEditableWithReplaceEl))
            throw new Error('Input event has raised');
    }

    function isTargetElement(actualTarget, expectedTarget) {
        return expectedTarget.contains(actualTarget);
    }

    document.addEventListener('textInput', onTextInput, true);
    document.addEventListener('textinput', onTextInput, true);
    document.addEventListener('input', onInput, true);
</script>
</html>
